package com.stox.client.workbench.ui.javafx.view;

import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.stage.Screen;

public class ViewResizeRelocateMouseEventHandler implements
		EventHandler<MouseEvent> {

	private View view;
	private double offsetX;
	private double offsetY;
	private double border = 4;
	private boolean active = false;
	
	public void applyStageResizeRelocateMouseEventHandler(View view) {
		this.view = view;
		
		view.addEventFilter(MouseEvent.MOUSE_PRESSED, this);
		view.addEventFilter(MouseEvent.MOUSE_MOVED, this);
		view.addEventFilter(MouseEvent.MOUSE_DRAGGED, this);
		view.addEventFilter(MouseEvent.MOUSE_RELEASED, this);
		
		view.getTitleBar().addEventHandler(MouseEvent.MOUSE_PRESSED,this);
		view.getTitleBar().addEventHandler(MouseEvent.MOUSE_MOVED, this);
		view.getTitleBar().addEventHandler(MouseEvent.MOUSE_DRAGGED,this);
		view.getTitleBar().addEventHandler(MouseEvent.MOUSE_CLICKED,this);
		view.getTitleBar().addEventHandler(MouseEvent.MOUSE_RELEASED,this);
	}
	
	@Override
	public void handle(MouseEvent event) {
		if(event.isConsumed()) return;
		
		double x = view.getLayoutX() +  event.getX();
		double y = view.getLayoutY() + event.getY();
		
		if (MouseEvent.MOUSE_MOVED.equals(event.getEventType()) || MouseEvent.MOUSE_RELEASED.equals(event.getEventType())) {
			setCursor(x, y);
		}else if (MouseEvent.MOUSE_PRESSED.equals(event.getEventType())) {
			offsetX = event.getX();
			offsetY = event.getY();
		} else if (MouseEvent.MOUSE_DRAGGED.equals(event.getEventType())) {
			if(Cursor.DEFAULT.equals(view.getCursor()) && 
					y < view.getLayoutY() + view.getTitleBar().getLayoutY() + view.getTitleBar().getHeight()){
				relocate(x, y);
				event.consume();
			}else{
				resize(event.getX(), event.getY());
				offsetX = event.getX();
				offsetY = event.getY();
			}
		}else if(MouseEvent.MOUSE_CLICKED.equals(event.getEventType()) && event.getClickCount() == 2){
			toggleMaximized();
			event.consume();
		}
	}
	
	public void toggleMaximized(){
		double x = view.getLayoutX() < 0 ? 0 : view.getLayoutX();
		double y = view.getLayoutY() < 0 ? 0 : view.getLayoutY();
		Screen screen = (Screen)Screen.getScreensForRectangle(x, y, 1d, 1d).get(0);
		
		if (view.isMaximized()) {
			view.setMaximized(false);
			if (view.getBackupWindowBounds() != null) {
				view.setLayoutX(view.getBackupWindowBounds().getMinX());
				view.setLayoutY(view.getBackupWindowBounds().getMinY());
				view.setMinWidth(view.getBackupWindowBounds().getWidth());
				view.setMinHeight(view.getBackupWindowBounds().getHeight());
			}
		} else {
			view.setMaximized(true);
			view.setBackupWindowBounds(new Rectangle2D(view.getLayoutX(),view.getLayoutY(),view.getWidth(),view.getHeight()));
			view.setLayoutX(screen.getVisualBounds().getMinX());
			view.setLayoutY(screen.getVisualBounds().getMinY());
			view.setMinWidth(screen.getVisualBounds().getWidth());
			view.setMinHeight(screen.getVisualBounds().getHeight());
		}
	}
	
	private void relocate(double x, double y){
		view.setLayoutX(x - offsetX);
		view.setLayoutY(y - offsetY); 
	}
	
	private void setCursor(double x, double y){
		double viewX = view.getLayoutX();
		double viewY = view.getLayoutY();
		double viewHeight = view.getHeight();
		double viewWidth = view.getWidth();
		
		 if (x < viewX + border && y < viewY + border) {
				view.setCursor(Cursor.NW_RESIZE);
				active = true;
			} else if(x > viewX + viewWidth - border && y < viewY + border){
				view.setCursor(Cursor.NE_RESIZE);
				active = true;
			}else if(x > viewX + viewWidth - border && y > viewY + viewHeight - border){
				view.setCursor(Cursor.SE_RESIZE);
				active = true;
			}else if(x < viewX + border && y > viewY + viewHeight - border){
				view.setCursor(Cursor.SW_RESIZE);
				active = true;
			}else if (x < viewX + border) {
				view.setCursor(Cursor.W_RESIZE);
				active = true;
			}else if (y < viewY + border) {
				view.setCursor(Cursor.N_RESIZE);
				active = true;
			}else if(x > viewX + viewWidth - border){
				view.setCursor(Cursor.E_RESIZE);
				active = true;
			}else if(y > viewY + viewHeight - border){
				view.setCursor(Cursor.S_RESIZE);
				active = true;
			}else {
				if(active){
					view.setCursor(Cursor.DEFAULT);
					active = false;
				}
			}
	}
	
	private void resize(double x, double y){
		double minWidth = view.getWidth() > view.getMinWidth() ? view.getMinWidth() : border*2;
		double minHeight = view.getHeight() > view.getMinHeight() ? view.getMinHeight() : border*2;
		Cursor cursor = view.getCursor();
		if(Cursor.W_RESIZE.equals(cursor)){
			resizeWest(minWidth, x);
		}else if(Cursor.NW_RESIZE.equals(cursor)){
			resizeWest(minWidth, x);
			resizeNorth(minHeight, y);
		}else if(Cursor.N_RESIZE.equals(cursor)){
			resizeNorth(minHeight, y);
		}else if(Cursor.NE_RESIZE.equals(cursor)){
			resizeNorth(minHeight, y);
			resizeEast(minWidth, x);
		}else 	if(Cursor.E_RESIZE.equals(cursor)){
			resizeEast(minWidth, x);
		}else if(Cursor.SE_RESIZE.equals(cursor)){
			resizeEast(minWidth, x);
			resizeSouth(minHeight, y);
		}else if(Cursor.S_RESIZE.equals(cursor)){
			resizeSouth(minHeight, y);
		}else if(Cursor.SW_RESIZE.equals(cursor)){
			resizeSouth(minHeight, y);
			resizeWest(minWidth, x);
		}
		view.autosize();
	}
	
	private void resizeWest(double minWidth, double x){
		double w = view.getWidth() - x;
		if(w >= minWidth){
			view.setMinWidth(w);
			view.setMaxWidth(w);
			view.setLayoutX(view.getLayoutX() + x);
		}
	}
	
	private void resizeNorth(double minHeight, double y){
		double h = view.getHeight() - y;
		if(h >= minHeight ){
			view.setMinHeight(h);
			view.setMaxHeight(h);
			view.setLayoutY(view.getLayoutY() + y);
		}
	}
	
	private void resizeEast(double minWidth, double x){
		if(x >= minWidth){
			view.setMaxWidth(x);
			view.setMinWidth(x);
		}
	}
	
	private void resizeSouth(double minHeight, double y){
		if(y >= minHeight ){
			view.setMinHeight(y);
			view.setMaxHeight(y);
		}
	}
	
}
